package com.tang.algorithm.multithreading;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author tlm
 * @version 1.0
 * @date 2020/4/20 8:56
 * 按序打印
 * 三个不同的线程将会共用一个 Foo 实例。
 * <p>
 * 线程 A 将会调用 one() 方法
 * 线程 B 将会调用 two() 方法
 * 线程 C 将会调用 three() 方法
 * 请设计修改程序，以确保 two() 方法在 one() 方法之后被执行，three() 方法在 two() 方法之后被执行。
 * <p>
 *  
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/print-in-order
 */
public class PrintInOrder {
}

class Foo {
    private Lock lock = new ReentrantLock();
    private Condition condition1 = lock.newCondition();
    private Condition condition2 = lock.newCondition();
    int temp = 0;

    public Foo() {

    }

    public void first(Runnable printFirst) throws InterruptedException {
        lock.lock();
        try{
            // printFirst.run() outputs "first". Do not change or remove this line.
            printFirst.run();
            temp = 1;
            condition1.signal();
        }
        finally {
            lock.unlock();
        }

    }

    public void second(Runnable printSecond) throws InterruptedException {
        lock.lock();
        try {
            while (temp != 1) {
                condition1.await();
            }
            // printSecond.run() outputs "second". Do not change or remove this line.
            printSecond.run();

            temp = 2;
            condition2.signal();

        } finally {
            lock.unlock();
        }

    }

    public void third(Runnable printThird) throws InterruptedException {
        lock.lock();
        try {
            while (temp != 2) {
                condition2.await();
            }
            // printThird.run() outputs "third". Do not change or remove this line.
            printThird.run();
        }finally {
            lock.unlock();
        }

    }
}